package cmd

import (
	"context"
	"fmt"
	"time"

	"github.com/chromedp/cdproto/page"
	"github.com/chromedp/chromedp"
	"github.com/spf13/cobra"
)

func init() {
	rootCmd.AddCommand(simCmd)
}

type SimTarget string

const (
	LoginST SimTarget = "login"
	ClickST SimTarget = "click"
)

func (s SimTarget) String() string {
	switch s {
	case LoginST:
		return "login"
	case ClickST:
		return "click"
	}
	return "unknown"
}

func (e *SimTarget) Scan(src interface{}) error {
	switch s := src.(type) {
	case []byte:
		*e = SimTarget(s)
	case string:
		*e = SimTarget(s)
	default:
		return fmt.Errorf("unsupported scan type for SimTarget: %T", src)
	}
	return nil
}

var simCmd = &cobra.Command{
	Use:   "sim",
	Short: "Make specific simulation of dp",
	Long:  `Make specific simulation of dp`,
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) == 0 {
			slog.Error("need simulate target.[login,click] available")
			return
		}
		targetPtr := new(SimTarget)
		if targetPtr.Scan(args[0]) != nil {
			slog.Error("no such simulate target.[login,click] available")
			return
		}

		fmt.Println("simulate target => ", *targetPtr)
		Simulate(*targetPtr)
	},
}

func Simulate(target interface{}) {
	ctx, cancel := chromedp.NewExecAllocator(
		context.Background(),
		markChromeDpFlags()...,
	)
	defer cancel()
	ctx, cancel = context.WithTimeout(ctx, 300*time.Second)
	defer cancel()
	ctx, cancel = chromedp.NewContext(
		ctx,
		chromedp.WithLogf(slog.Debugf),
	)
	defer cancel()

	const script = `(function(w, n, wn) {
		// Pass the Webdriver Test.
		Object.defineProperty(n, 'webdriver', {
			get: () => false,
		});
	
		// Pass the Plugins Length Test.
		// Overwrite the plugins property to use a custom getter.
		Object.defineProperty(n, 'plugins', {
			// This just needs to have length > 0 for the current test,
			// but we could mock the plugins too if necessary.
			get: () => [1, 2, 3, 4, 5],
		});
	
		// Pass the Languages Test.
		// Overwrite the plugins property to use a custom getter.
		Object.defineProperty(n, 'languages', {
			get: () => ['en-US', 'en'],
		});
	
		// Pass the Chrome Test.
		// We can mock this in as much depth as we need for the test.
		w.chrome = {
			runtime: {},
		};
	
		// Pass the Permissions Test.
		const originalQuery = wn.permissions.query;
		return wn.permissions.query = (parameters) => (
			parameters.name === 'notifications' ?
				Promise.resolve({ state: Notification.permission }) :
				originalQuery(parameters)
		);
	
	})(window, navigator, window.navigator);`

	var scriptID page.ScriptIdentifier
	byPassAction := chromedp.ActionFunc(func(ctx context.Context) error {
		var err error
		scriptID, err = page.AddScriptToEvaluateOnNewDocument(script).Do(ctx)
		if err != nil {
			return err
		}
		return nil
	})
	switch target {
	case LoginST:
		slog.Info("Simulate Login...")
		loginUrl := `https://account.dianping.com/pclogin`
		var segment string
		err := chromedp.Run(ctx,
			byPassAction,
			chromedp.Navigate(loginUrl),
			// wait for footer element is visible (ie, page is loaded)
			chromedp.WaitVisible(`.pc-icon`),
			// find and click "Example" link
			chromedp.Click(`.pc-icon`, chromedp.NodeVisible),
			chromedp.WaitVisible(`.segment-label-grey`),
			chromedp.WaitVisible(`#pc-check`),
			chromedp.Click(`.segment-label-grey`, chromedp.NodeVisible),
			chromedp.Click(`#pc-check`, chromedp.NodeVisible),
			chromedp.WaitVisible(`#mobile-number-textbox`),
			chromedp.WaitVisible(`#password-textbox`),
			chromedp.SetValue(`#mobile-number-textbox`, "13757140245"),
			chromedp.SetValue(`#password-textbox`, "jiaoda615"),
			chromedp.WaitVisible(`.button-pc`),
			chromedp.Text(`.segment-label-grey`, &segment),
			chromedp.Sleep(1*time.Second),
			// chromedp.Click(`.button-pc`),
			// retrieve the text of the textarea
			// chromedp.Text(`.segment-label-grey`, &segment),
			chromedp.WaitSelected(".button-pc111"),
		)
		if err != nil {
			slog.Fatal(err)
		}
		slog.Infof("dp login:\n%s", scriptID)
	case ClickST:
		slog.Info("Simulate Click...")
		var example string
		err := chromedp.Run(ctx,
			chromedp.Navigate(`https://pkg.go.dev/time`),
			// wait for footer element is visible (ie, page is loaded)
			chromedp.WaitVisible(`body > footer`),
			// find and click "Example" link
			chromedp.Click(`#example-After`, chromedp.NodeVisible),
			// retrieve the text of the textarea
			chromedp.Value(`#example-After textarea`, &example),
		)
		if err != nil {
			slog.Fatal(err)
		}
		slog.Infof("Go's time.After example:\n%s", example)
	default:
		slog.Info("Simulate Index...")
		// indexUrl := "https://www.dianping.com/shop/G6pGlEns2VFNYly8"
		err := chromedp.Run(ctx,
			preTasks(),
			simTasks(),
			// chromedp.Navigate(indexUrl),
			// wait for footer element is visible (ie, page is loaded)
			chromedp.WaitSelected(".button-pc111"),
		)
		if err != nil {
			slog.Fatal(err)
			chromedp.Stop()
		}
		// slog.Infof("dp index:\n%s", scriptID)
	}

}

// const loginURL = "https://account.wps.cn/"

// 自定义任务
func simTasks() chromedp.Tasks {
	return chromedp.Tasks{
		// 0. 加载cookies
		// loadCookies(),

		// 1. 打开金山文档的登陆界面
		chromedp.Navigate(`https://account.dianping.com/pclogin`),
		// 判断一下是否已经登陆
		// checkLoginStatus(),

		// 2. 点击微信登陆按钮
		// #wechat > span:nth-child(2)
		// chromedp.Click(`#wechat > span:nth-child(2)`),

		// 3. 点击确认按钮
		// #dialog > div.dialog-wrapper > div > div.dialog-footer > div.dialog-footer-ok
		// chromedp.Click(`#dialog > div.dialog-wrapper > div > div.dialog-footer > div.dialog-footer-ok`),
		// 4. 获取二维码
		// #wximport
		// getQRCode(),

		// 5. 若二维码登录后，浏览器会自动跳转到用户信息页面
		// saveCookies(),
	}
}
